#pragma once
#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <atomic> //原子性变量

namespace threadpool
{
    // 定义任务类型
    using task = std::function<void(void)>;
    class threadpool
    {
    public:
        threadpool(size_t thread_num = 5)
            : _is_runing(true)
        {
            // 初始化线程
            for (int i = 0; i < thread_num; i++)
            {
                _threads.emplace_back(&threadpool::entrance, this);
            }
        }
        // 实现一个插入任意函数参数, 不需要线程执行的结果
        template <typename Fun, typename... Args>
        void push(Fun &&F, Args &&...args)
        {
            // 绑定参数
            task t = std::bind(std::forward<Fun>(F), std::forward<Args>(args)...);
            {
                std::unique_lock<std::mutex> lock(_mtx);
                _taskpool.push(t);
            }
            _cv.notify_one(); // 有任务了就唤醒一个线程
        }

        void stop()
        {
            if (!_is_runing)
            {
                return;
            }
            _is_runing = false;
            _cv.notify_all(); // 唤醒所有的线程，准备退出
            for (auto &thread : _threads)
            {
                thread.join(); // 线程退出
            }
        }

        // 等待所有任务结束
        void wait_all()
        {
            while (true)
            {
                {
                    std::unique_lock<std::mutex> lock(_mtx);
                    if (_taskpool.empty())
                        break; // 队列已空则退出
                }
                std::this_thread::yield(); // 让出CPU，避免忙等待
            }
        }

        ~threadpool()
        {
            stop();
        }

    private:
        // 每一个线程都需要执行的入口函数
        void entrance()
        {
            while (_is_runing)
            {
                task t;
                {
                    std::unique_lock<std::mutex> lock(_mtx);
                    _cv.wait(lock, [this]() { // wait 后面lambdaba表达式为true, 就在条件变量后面等待
                        return !_is_runing || !_taskpool.empty();
                    });
                    // 防止t为空
                    if (!_is_runing && _taskpool.empty())
                    {
                        break;
                    }

                    t = _taskpool.front();
                    _taskpool.pop();
                }
                t();
            }
        }

    private:
        std::atomic<bool> _is_runing;
        std::queue<task> _taskpool; // 任务池
        std::vector<std::thread> _threads;
        // 锁和条件变量实现同步
        std::mutex _mtx;
        std::condition_variable _cv;
    };
}